package com.gfl.trivialrestclient.services.impl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.gfl.trivialrestclient.dao.UserDao;
import com.gfl.trivialrestclient.model.User;
import com.gfl.trivialrestclient.services.LoginService;

@Service
public class LoginServiceImpl implements LoginService {
	private SecurityContextRepository securityContextRepository;
	private AuthenticationManager authenticationManager;
	private UserDao userDao;

	@Autowired
	public void setAuthenticationManager(
			AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	@Autowired
	public void setSecurityContextRepository(
			SecurityContextRepository securityContextRepository) {
		this.securityContextRepository = securityContextRepository;
	}

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Transactional(readOnly = true)
	@Override
	public User getLoggedUser() {
		User user = null;

		UserDetails userDetails = getLoggedUserDetails();
		if (userDetails != null) {
			user = userDao.findByUsername(userDetails.getUsername());
		}

		return user;
	}

	@Override
	public UserDetails getLoggedUserDetails() {
		UserDetails userDetails = null;
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();

		if (isAuthentificated(authentication)) {
			Object principal = authentication.getPrincipal();
			if (principal instanceof UserDetails) {
				userDetails = (UserDetails) principal;
			}
		}

		return userDetails;
	}

	@Override
	public void webLogin(String login, String password,
			HttpServletRequest request, HttpServletResponse response)
			throws BadCredentialsException {
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
				login, password);
		Authentication auth = authenticationManager.authenticate(token);
		SecurityContextHolder.getContext().setAuthentication(auth);
		// force saving of security context to http session and seting of
		// coockie for browser ad ajax reuqests
		securityContextRepository.saveContext(
				SecurityContextHolder.getContext(), request, response);
	}

	@Override
	public void logout() {
		SecurityContextHolder.getContext().setAuthentication(null);
	}

	@Override
	public boolean isLoggedIn() {
		Authentication authentication = SecurityContextHolder.getContext()
				.getAuthentication();
		return isAuthentificated(authentication);
	}

	/**
	 * Check if user authentificated and not anonimus
	 * 
	 * @param authentication
	 * @return
	 */
	private boolean isAuthentificated(Authentication authentication) {
		return authentication != null
				&& !(authentication instanceof AnonymousAuthenticationToken)
				&& authentication.isAuthenticated();
	}

}
